package com.example.gulimall.ware.listener;

import com.example.common.config.rabbit.common.RabbitTemplateWrapper;
import com.example.common.config.rabbit.ware.WareTransactionalConfig;
import com.example.common.constant.MessageConstant;
import com.example.common.constant.RabbitContent;
import com.example.common.entity.order.OrderEntity;
import com.example.gulimall.ware.service.WareSkuService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * <p>
 * 此处处理消息
 * 发送消息 {@see WareSkuServiceImpl#saveTaskDetailsAndSend(java.util.List)}
 * </p>
 *
 * @author zyred
 * @since v 0.1
 **/
@Slf4j
@Configuration
@RabbitListener(queues = WareTransactionalConfig.NORMAL_QUEUE)
public class StockReleaseListener {

    @Autowired
    private WareSkuService wareSkuService;
    @Autowired
    private RabbitTemplateWrapper rabbitTemplateWrapper;

    /**
     * 处理库存锁定的商品
     * 解锁商品的条件：
     * 1. 下单成功，库存锁定成功，但是订单创建失败导致订单回滚，库存未回滚
     * 1.1 ： 订单号存在数据库中，真正下单成功
     * 1.1.1：如果订单状态已取消 -- 解锁
     * 1.1.2：如果非取消状态    -- 不能解锁
     * 1.2 ： 订单号不存在数据库中，直接解锁库存     -- 解锁
     * 2. 库存锁定失败，在本业务中，不存在库存锁定失败且发送消息成功的问题，所以不考虑
     *
     * @param container 接收到的数据
     * @param channel   rabbitMQ 组件
     * @param message   rabbitMQ 组件
     */
    @RabbitHandler
    public void handleStockRelease(List<LinkedHashMap<String, Object>> container,
                                   Channel channel, Message message) throws IOException {

        // 主动消费：库存服务主动监听库存队列
        log.info("主动消费 - 解锁库存：{}", container);

        long tag = message.getMessageProperties().getDeliveryTag();
        // 从请求头中获取 ID
        String id = (String) message.getMessageProperties()
                .getHeaders().get(RabbitContent.RABBIT_KEY);

        try {
            this.wareSkuService.unlockStock(container);
            channel.basicAck(tag, false);

            // 消费成功后，修改消息为成功
            this.rabbitTemplateWrapper.alertStatusAsync(
                    MessageConstant.MessageStatus.SPENDING.getCode(),
                    null, id);

        } catch (Exception ex) {

            ex.printStackTrace();
            channel.basicReject(tag, true);

            // 消费失败后，将消息修改为失败状态
            this.rabbitTemplateWrapper.alertStatusAsync(
                    MessageConstant.MessageStatus.SPENDING_ERROR.getCode(),
                    ex.getMessage(), id);
        }
    }


    @RabbitHandler
    public void handleStockRelease(OrderEntity order,
                                   Channel channel, Message message) throws IOException {

        // 被动消费：库存服务被订单服务提醒后
        log.info("被动消费 - 解锁库存 ：{}", order);

        long tag = message.getMessageProperties().getDeliveryTag();

        try {
            this.wareSkuService.unlockStock(order);
            channel.basicAck(tag, false);
        } catch (Exception ex) {
            ex.printStackTrace();
            channel.basicReject(tag, true);
        }
    }
}
